home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / SourceCode / AdobeExamples / NX_ImportAdv / DocView.m < prev    next >
Text File  |  1992-12-19  |  10KB  |  358 lines

  1.  
  2. /*
  3.  * (a)  (C) 1990 by Adobe Systems Incorporated. All rights reserved.
  4.  *
  5.  * (b)  If this Sample Code is distributed as part of the Display PostScript
  6.  *    System Software Development Kit from Adobe Systems Incorporated,
  7.  *    then this copy is designated as Development Software and its use is
  8.  *    subject to the terms of the License Agreement attached to such Kit.
  9.  *
  10.  * (c)  If this Sample Code is distributed independently, then the following
  11.  *    terms apply:
  12.  *
  13.  * (d)  This file may be freely copied and redistributed as long as:
  14.  *    1) Parts (a), (d), (e) and (f) continue to be included in the file,
  15.  *    2) If the file has been modified in any way, a notice of such
  16.  *      modification is conspicuously indicated.
  17.  *
  18.  * (e)  PostScript, Display PostScript, and Adobe are registered trademarks of
  19.  *    Adobe Systems Incorporated.
  20.  * 
  21.  * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
  22.  *    CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
  23.  *    AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
  24.  *    ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
  25.  *    OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
  26.  *    WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
  27.  *    WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
  28.  *    DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
  29.  *    FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
  30.  *    OF THIRD PARTY RIGHTS.
  31.  */
  32.  
  33. /*
  34.  *    DocView.m
  35.  *
  36.  *    This class handles the scaling of the drawing view. It repositions
  37.  *    The drawing view within itself if the drawing view is smaller than the
  38.  *    size of the clip view. The size of the doc view is:
  39.  *    MAX(clip view frame, drawing view frame).
  40.  *
  41.  *    This class is used in several of the other Display PostScript programs.
  42.  *    Some of the methods may be different as the class became more and
  43.  *    more refined but the general operation remains the same.
  44.  *
  45.  *    Version:    2.0
  46.  *    Author:    Ken Fromm
  47.  */
  48.  
  49. #import "DocView.h"
  50. #import "ImportApp.h"
  51.  
  52. #import <appkit/Cursor.h>
  53. #import <appkit/Matrix.h>
  54. #import <appkit/ScrollView.h>
  55. #import <dpsclient/wraps.h>
  56. #import <appkit/nextstd.h>
  57.  
  58. @implementation DocView
  59.  
  60. /*
  61. *    Since there is only one subview its easier to keep track of it as an
  62. *    instance variable rather than in the subview list. 
  63. */
  64. - setDrawView:newView
  65. {
  66.     id        oldView;
  67.  
  68.     oldView = drawviewId;
  69.     [oldView  removeFromSuperview];
  70.  
  71.     [self  addSubview:newView];
  72.     drawviewId = newView;
  73.     
  74.     return oldView;
  75. }
  76.  
  77. - drawView
  78. {
  79.     return drawviewId;
  80. }
  81.  
  82. - setScale:(float)value
  83. {
  84.     scale = value;
  85.     
  86.     return self;
  87. }
  88.  
  89. - (float) scale
  90. {
  91.     return  scale;
  92. }
  93.  
  94. /*
  95. *    Check whether the frame of the drawingview is in the rectangle passed in.
  96. *    If drop is true, then include the linewidth and the drop shadow as part of the
  97. *    drawingview frame.
  98. */
  99. - getDrawViewInRect:(const NXRect *) aRect  withDrop:(BOOL) drop
  100. {
  101.     id        aView = NULL;
  102.  
  103.     NXRect    viewRect, dropRect;
  104.     
  105.     [drawviewId  getFrame:&viewRect];
  106.     if (drop)
  107.     {    
  108.         dropRect = viewRect;
  109.         NXOffsetRect(&dropRect, rint(OFFSET * scale), rint(-OFFSET * scale));
  110.         NXOffsetRect(&viewRect, rint(LINEWIDTH/2 * scale), rint(LINEWIDTH/2 * scale));
  111.         NXUnionRect(&dropRect, &viewRect);
  112.     }
  113.     if (NXIntersectsRect(aRect, &viewRect))
  114.         aView = drawviewId;
  115.  
  116.     return  aView;
  117. }
  118.  
  119. /*
  120. *    Sizes the drawing view from the old scale to the newscale.
  121. *    The frame of the view is used instead of the bounds because
  122. *    the bound will always be the same whereas the frame will
  123. *    provide the size in default coordinates.
  124. */
  125. - sizeView:viewId withScale:(float) newscale
  126. {
  127.     float            scalefactor, sizewidth, sizeheight;
  128.  
  129.     NXRect        viewFrame;
  130.     
  131.     [viewId  getFrame:&viewFrame];
  132.     scalefactor = newscale/scale;
  133.     sizewidth = viewFrame.size.width*scalefactor;
  134.     sizeheight = viewFrame.size.height*scalefactor;
  135.     [viewId sizeTo:rint(sizewidth) :rint(sizeheight)];
  136.  
  137.     return self;
  138. }
  139.  
  140. /* 
  141. *    Scales the drawing view from the old scale to the new scale.
  142. *    The scale method is relative so we use the ratio
  143. *    of the old scale to the new scale to obtain the scaling factor.
  144. */
  145. - scaleView:viewId  withScale:(float) newscale
  146. {
  147.     float     scalefactor;
  148.  
  149.     scalefactor = newscale/scale;
  150.     [viewId scale:scalefactor  :scalefactor];
  151.  
  152.     return self;
  153. }
  154.  
  155. /*
  156. *    Place the view passed in in the center of the doc view
  157. *    if it is smaller than the size of the ClipView. Two passes are made
  158. *    through the loop because adding or removing a horizontal or
  159. *    vertical scrollbar will affect the size of the remaining dimension .
  160. */
  161. - placeView:viewId
  162. {
  163.     BOOL        vert = NO, horiz = NO, done = NO;
  164.  
  165.     int            passes = 0, border_type;
  166.  
  167.     float            margin;
  168.     
  169.     NXSize        contSize, newSize, insetSize, delta;
  170.  
  171.     NXRect         viewFrame, scrollFrame;
  172.  
  173.     margin = 4 * OFFSET * scale;
  174.  
  175.     [viewId  getFrame:&viewFrame];
  176.     [[superview superview]  getFrame:&scrollFrame];
  177.     border_type = [[superview superview]  borderType];
  178.  
  179.     while (!done && ++passes <= 2)
  180.     {
  181.         [ScrollView getContentSize:&contSize forFrameSize:&scrollFrame.size
  182.             horizScroller:horiz  vertScroller:vert borderType:border_type];
  183.  
  184.         newSize.width = MAX(viewFrame.size.width, contSize.width);
  185.         newSize.height = MAX(viewFrame.size.height, contSize.height);
  186.  
  187.         delta.width = newSize.width - viewFrame.size.width;
  188.         delta.height = newSize.height - viewFrame.size.height;
  189.         if (delta.width != 0.0 || delta.height != 0.0)
  190.         {
  191.             if (delta.width < margin)
  192.                 newSize.width += margin - delta.width;
  193.             if (delta.height < margin)
  194.                 newSize.height += margin - delta.height;
  195.         }
  196.  
  197.         horiz = (newSize.width != contSize.width);
  198.         vert = (newSize.height != contSize.height);
  199.         if ((horiz && vert) || (!horiz && !vert))
  200.             done = YES;
  201.         else
  202.             done = NO;
  203.     }
  204.     
  205.     [self  sizeTo:newSize.width  :newSize.height];
  206.  
  207.     insetSize.width = floor((newSize.width - viewFrame.size.width)/2);
  208.     insetSize.height =  floor((newSize.height - viewFrame.size.height)/2);
  209.     [viewId  moveTo:insetSize.width  :insetSize.height];
  210.     if (insetSize.width != 0 || insetSize.height != 0)
  211.         [viewId  setClipping:YES];
  212.     else
  213.         [viewId setClipping:NO];
  214.  
  215.     if (horiz)
  216.         [[superview superview] setHorizScrollerRequired:YES];
  217.     else
  218.         [[superview superview] setHorizScrollerRequired:NO];
  219.     
  220.     if (vert)
  221.         [[superview superview] setVertScrollerRequired:YES];
  222.     else
  223.         [[superview superview] setVertScrollerRequired:NO];
  224.  
  225.     return self;
  226. }
  227.  
  228. /*
  229. *    Scales the view to the tag of the selected matrix cell and then
  230. *    scrolls to the point. The point is in window coordinates so
  231. *    it must be converted to the drawing view  coordinates in order
  232. *    to position it in the same relative place in the view.
  233. */
  234. - scaleDrawView:hitView  withEvent:(NXEvent *) event;
  235. {
  236.     float            newscale;
  237.  
  238.     NXPoint        viewPt;
  239.  
  240.     [window invalidateCursorRectsForView:self];
  241.  
  242.     if ((event->flags & NX_ALTERNATEMASK) == NX_ALTERNATEMASK)
  243.         newscale = scale / INCSCALE;
  244.     else
  245.         newscale = scale * INCSCALE;
  246.  
  247.     if (hitView && newscale >= MINSCALE && newscale <= MAXSCALE)
  248.     {
  249.         viewPt = event->location;
  250.         [self convertPoint:&viewPt fromView:nil];
  251.         [self convertPoint:&viewPt  toView:hitView];
  252.         [window disableDisplay];
  253.             /* Size and then scale the drawing view. The frame of the */
  254.             /* drawing view must reflect the changed size. Scaling */
  255.             /* alone will not change the frame. */
  256.             [self  sizeView:hitView  withScale:newscale];
  257.             [self  scaleView:hitView  withScale:newscale];
  258.             [self  setScale:newscale];
  259.     
  260.             [self  placeView:hitView];
  261.             [self  scrollPoint:&viewPt  inView:hitView  to:&event->location];
  262.         [window reenableDisplay];
  263.         [[window contentView]  display];
  264.     }
  265.     else
  266.         [NXApp  clearOperation];
  267.  
  268.     return self;
  269. }
  270.  
  271. /*
  272.  *    Use the point location relative to the window versus the point relative
  273.  *    to the drawing view (before the scale) to determine where to scroll
  274.  *    the drawing view. We want the same location in the drawing view to
  275.  *    appear where the mouse downed occurred.  The window coordinates
  276.  *    are used and then adjusted by the position of the scrolling frame
  277.  *    because the presence or absence of scrollbars throws the use
  278.  *    of the doc views coordinates awry.
  279.  */    
  280. - scrollPoint:(const NXPoint *) aPt  inView:hitView  to:(const NXPoint *) windowPt
  281. {
  282.     NXPoint        viewPt;
  283.  
  284.     NXSize        contSize;
  285.  
  286.     NXRect         viewFrame, visRect, scrollFrame;
  287.  
  288.     [[superview superview]  getContentSize:&contSize];
  289.     [hitView  getFrame:&viewFrame];
  290.  
  291.     if (viewFrame.size.width > contSize.width || viewFrame.size.height > contSize.height)
  292.     {
  293.         viewPt = *aPt;
  294.         [self  convertPoint:&viewPt  fromView:hitView];        
  295.         [self getVisibleRect:&visRect];
  296.         [[superview superview] getFrame:&scrollFrame];
  297.  
  298.         if (viewFrame.size.width > contSize.width)
  299.             viewPt.x  -= windowPt->x - (scrollFrame.origin.x +scrollFrame.size.width -
  300.                             visRect.size.width);
  301.  
  302.         if (viewFrame.size.height > contSize.height)
  303.             viewPt.y  -= windowPt->y - (scrollFrame.origin.y + scrollFrame.size.height -
  304.                             visRect.size.height);
  305.  
  306.         [self  scrollPoint:&viewPt];        
  307.     }
  308.  
  309.     return self;
  310. }
  311.  
  312. /*
  313.  * This drawSelf method draws a border around the drawing view as well as a
  314.  * drop shadow.  This is only done if it will be visible however. We tell if it is visible
  315.  * if the rectangle passed in is not contained entirely within drawingView frame.
  316. */
  317. - drawSelf:(NXRect *)r :(int) count
  318. {
  319.     id            visView;
  320.  
  321.     NXRect        drawRect, dropRect, bRect, xRect, yRect;
  322.  
  323.     visView = [self getDrawViewInRect:r  withDrop:YES];
  324.     if (visView)
  325.     {
  326.         /* Calculate the rectangle of the draw view plus its drop shadow. */
  327.         [visView  getFrame:&drawRect];
  328.         dropRect = bRect = drawRect;
  329.         NXOffsetRect(&bRect, -rint(LINEWIDTH/2 * scale), -rint(LINEWIDTH/2 * scale));
  330.         NXOffsetRect(&dropRect, rint(OFFSET * scale), rint(-OFFSET * scale));
  331.         NXUnionRect(&dropRect, &bRect);
  332.         if (!NXContainsRect(&bRect, r))
  333.         {
  334.             bRect = xRect = yRect = dropRect;
  335.             NXIntersectionRect(&drawRect, &bRect);
  336.             NXDivideRect(&xRect, &dropRect, bRect.size.width, 0);
  337.             NXDivideRect(&yRect, &dropRect, bRect.size.height, 3);
  338.  
  339.             PSgsave();
  340.                 PSsetgray(NX_BLACK);
  341.                 PSrectclip(r->origin.x, r->origin.y, r->size.width, r->size.height);
  342.                 PSrectfill(xRect.origin.x, xRect.origin.y,
  343.                     xRect.size.width, xRect.size.height);
  344.                 PSrectfill(yRect.origin.x, yRect.origin.y,
  345.                     yRect.size.width, yRect.size.height);
  346.                 PSsetlinewidth(LINEWIDTH * scale);
  347.                 PSrectstroke(drawRect.origin.x, drawRect.origin.y,
  348.                     drawRect.size.width, drawRect.size.height);
  349.             PSgrestore();
  350.         }
  351.     }
  352.  
  353.     return self;            
  354. }
  355.  
  356. @end
  357.  
  358.